<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=yes">
  
  
  <title>  Java 如何选择最具体的方法执行（翻译） |   XHX 博客 </title>

 
  
    <link rel="icon" href="/images/favicon.ico">
  


  <link rel="stylesheet" href="/nayo.min.css"> 
</head>  
  <body>   
    
      <header class="header">
	
  <nav class="header-nav">        

    <span class="iconfont icon-menu mobile-toggle"></span>   	

    <div class="header-logo">
      <a href="/">
        <img class="header-logo-img" src="/images/head.JPG">
      </a>
    </div>

    <div class="header-menu">          
              
          
            <a class="header-menu-link" id="header-menu-home" href="/">
              <i class="iconfont icon-home">  
            </i></a>     
          
              
          
            <a class="header-menu-link" id="header-menu-archives" href="/archives">
              <i class="iconfont icon-archives">  
            </i></a>     
          
              
          
            <a class="header-menu-link" id="header-menu-tags" href="/tags">
              <i class="iconfont icon-tags">  
            </i></a>     
          
              
          
            <a class="header-menu-link" id="header-menu-about" href="/about">
              <i class="iconfont icon-about">  
            </i></a>     
          
              
          
              <a class="header-menu-link" id="header-menu-search">
                <i class="iconfont icon-search">  
              </i></a>
          
                  
    </div>  
    
  </nav>
</header>

   

      <div class="container">       
          
          
            <section class="main">  
          

          <article class="post">
  
	<div class="post-header">

	<p class="post-title">	
		java 如何选择最具体的方法执行（翻译）
	</p>
			

	<div class="meta-info">	
	<span>
		Sep 26, 2018
	</span>

	
	
		<i class="iconfont icon-words"></i>
		<span>
			2270
		</span>
	
</div>

</div> 
	
    <script type="text/x-mathjax-config">
        var post = document.getElementsByClassName("post")[0];  
        MathJax.Hub.Config({
            showProcessingMessages: false,
            messageStyle: "none",    
            tex2jax: {
                inlineMath:  [ ["$", "$"] , ["\\(","\\)"]],
                displayMath: [ ["$$","$$"] , ["\\[","\\]"]],
                skipTags: ['script', 'noscript', 'style', 'textarea', 'pre','code','a'],
            },
            "HTML-CSS": {            
                showMathMenu: false
            }
        });
        MathJax.Hub.Queue(["Typeset",MathJax.Hub,post]);
    </script>
    <style>.MathJax{outline:0;}</style>

    <script type="text/javascript" src="//cdn.bootcss.com/mathjax/2.7.2/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
 

	  <div class="typo post-content slideDownMin">

		

			
					<p>  方法调用的时候，有2个以上的成员方法都是可访问且适配，就必须要为运行时选择一个方法描述符。Java 语言选择的规则是：最具体的方法。</p>
<p>  简单讲就是在方法调用传递的时候不会产生任何编译时错误的前提下，一个方法比另一个方法更具体。在参数确定的 lambda 表达式或原始数据类型调用的情况下，签名可以灵活调整。<br><a id="more"></a><br>  设方法调用的参数表达为：$e_1, …, e_k$，如果一个适配的方法 $m_1$ 比另一个适配的方法 $m_2$ 更具体，需要满足以下任一个条件：</p>
<ol>
<li><p>$m_2$ 是泛方法，那么 $m_1$ 在参数 $e_1, …, e_k$ 上比 $m_2$ 更具体。(见18.5.4)</p>
</li>
<li><p>$m_2$ 不是泛方法，$m_1$ 和 $m_2$ 对于调用的适配有的宽松有的严格，$m_1$参数类型：$S_1, …, S_n$，$m_2$ 参数类型：$T_1, …, T_n$，每一个 $e_i$ 都有 $S_i$ 比 $T_i$ 更具体。</p>
</li>
<li><p>$m_2$ 不是泛方法，$m_1$ 和 $m_2$ 都适配原始类型做参数的方法调用，$m_1$ 的前 k 个变量参数是：$S_1, …, S_k$，$m_2$ 的前 k 个变量参数是：$T_1, …, T_k$，对每一个 $e_i$ 都有 $S_i$ 比 $T_i$ 更具体。但是 $m_1$ 的第 k + 1个参数是 $m_2$ 的子类型。</p>
</li>
</ol>
<p>上述条件仅适用于一个方法比另一个方法更具体的情况。</p>
<p>如果 $S &lt;: T$那么 S 比 T 类型更具体。(参见JLS4.10)</p>
<p>对于表达式 e， 如果 T 不是 S 的子类型，满足以下条件时，接口类型 S 才会比接口类型 T 更具体：</p>
<blockquote>
<p>设 $U_1, …, U_k$ 和 $R_1$ 分别是方法 S 的参数类型和返回类型；$V_1, …, V_k$ 和 $R_2$ 分别是方法 T 的参数类型和返回值类型。</p>
</blockquote>
<ul>
<li>如果 e 是特定类型的 labmda 表达式，那么下面一项成立：<ul>
<li>$R_2$ 是void</li>
<li>$R_1 &lt;: R_2$</li>
<li>$R_1$ 和 $R_2$ 是接口类型，至少有一个 return，且每个 e 的 return 都有$R_1$ 比 $R_2$ 更具体。<br>(代码块方法体的 lambda 表达式的 return 在15.27.2定义。表达式方法体的 lambda 表达式的 return 就是自身。)</li>
<li>$R_1$ 是原始类型，$R_2$ 是引用类型，至少存在一个 return，且每个 e 的 return 是独立的原始类型的表达式。</li>
<li>$R_1$是引用类型，$R_2$是原始类型，至少存在一个 return，且每个 e 的 return 是独立的引用类型表达式或[多项表达式][2]<br>(多项表达式这里的含义可以一句话总结：根据不同的输入情况，输出结果可能有不同的数据类型)</li>
</ul>
</li>
<li>如果 e 是复合表达式，情况中的一种递归应用到包含的表达式中。</li>
<li>如果 e 是条件表达式，对每第二个和第三个操作递归操作。</li>
</ul>
<p>方法 $m_1$ 比方法 $m_2$ 严格具体，当且仅当 $m_1$ 比 $m_2$ 更具体且 $m_2$ 不比 $m_1$更具体。</p>
<p>方法对于方法调用<code>最大具体</code>：可访问性和适配度没有比它更严格具体的。</p>
<p>如果只有一个<code>最大具体</code>的方法，那么就叫方法调用<code>最具体</code>的方法，这个最具体的方法肯定比其他可访问的适配的方法。接下来就是其他的编译时的检查的任务了，参见15.12.3。</p>
<p>也有可能找不到最具体的方法，可能存在多个方法是最大具体。这种情况：</p>
<ul>
<li>如果所有最大具体的方法都有<a href="#appendix">等价继承的签名</a>:<ul>
<li>如果只有一个方法是具体的(非 <code>abstract</code>的)，那它就是最具体的方法。</li>
<li>否则，如果所有的方法都是 abstract 或者默认的，所有的方法签名都有相同的擦除，那就直接取返回值最具体的那个方法。<br>这种情况下，最具体的方法可能是 abstract 的。最具体的方法可能抛出检查异常当且仅当异常或者擦除在每个最大具体方法的 throws 从句中声明。</li>
</ul>
</li>
<li>否则，方法调用就是<code>ambiguous</code>的，编译时错误抛出。</li>
</ul>
<p><a name="appendix"></a></p>
<h2 id="Appendix："><a href="#Appendix：" class="headerlink" title="Appendix："></a>Appendix：</h2><ol>
<li><p>继承等价的签名:</p>
<p> A 擦除后和 B 相同，则 A 是 B 的子方法签名，B 擦除后也和 A 相同，则两者继承等价。</p>
</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Point</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> x, y;</span><br><span class="line">    <span class="function"><span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title">move</span><span class="params">(<span class="keyword">int</span> dx, <span class="keyword">int</span> dy)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">move</span><span class="params">(<span class="keyword">int</span> dx, <span class="keyword">int</span> dy)</span> </span>&#123; x += dx; y += dy; &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>❌同一个类里的继承等价会导致编译时错误。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CollectionConverter</span> </span>&#123;</span><br><span class="line">    <span class="function">List <span class="title">toList</span><span class="params">(Collection c)</span> </span>&#123;...&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Overrider</span> <span class="keyword">extends</span> <span class="title">CollectionConverter</span> </span>&#123;</span><br><span class="line">    <span class="function">List <span class="title">toList</span><span class="params">(Collection c)</span> </span>&#123;...&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>❗️这里的 CollectionConverter 如果修改就会导致 Overrider 代码出错。<br>&lt;/a&gt;</p>
<h2 id="References"><a href="#References" class="headerlink" title="References:"></a>References:</h2><p>[1]: <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5" target="_blank" rel="noopener">https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5</a> Choosing the Most Specific Method<br>[2]: <a href="http://cr.openjdk.java.net/~dlsmith/jsr335-0.6.1/D.html" target="_blank" rel="noopener">http://cr.openjdk.java.net/~dlsmith/jsr335-0.6.1/D.html</a> Lambda Specification, Part D: Poly Expressions<br>[3]: <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.2" target="_blank" rel="noopener">https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.2</a> Method Signature</p>
  	
					
	  </div>     
	  

	<div class="post-footer">

  <div class="post-footer-other">
      <span class="post-footer-item">
        




<span class="donate-btn">
	<span class="iconfont icon-donate"></span>
</span>


<div id="donate-box" class="sildeUpMin">

	<span class="donate-cancel iconfont icon-cancel"></span>

	<div class="donate-img-box">
		<img id="donate-qr-wechat" class="noLazyLoad donate-img" src="/images/donate1.png" alt="No Donate Image!">	
		<img id="donate-qr-alipay" class="noLazyLoad donate-img" src="/images/donate2.png" alt="No Donate Image!">	
	</div>

	<span class="donate-word">希望本文对你有帮助~</span>

	<div class="donate-list">
		<span class="iconfont icon-donate-wechat"></span>
		<span class="iconfont icon-donate-alipay"></span>
	</div>

</div>

 
      </span>           
      <span class="post-footer-item">
        
	
<script id="-mob-share" src="http://f1.webshare.mob.com/code/mob-share.js?appkey=29a4323345125"></script>
	
	<span class="share-btn">
	<span class="iconfont icon-share"></span>
	</span>


	<div class="-mob-share sildeUpMin">
		<div class="-mob-inner">
		   			             
            <a class="iconfont icon-share-qq -mob-share-link"></a>		
     	   			             
            <a class="iconfont icon-share-weixin -mob-share-link"></a>		
     	   			             
            <a class="iconfont icon-share-weibo -mob-share-link"></a>		
     	   
		</div>
	</div>	

      </span>           
  </div>  

  <div class="post-footer-meta">
        	

        
          <i class="iconfont icon-tag"></i>     
            <a class="tag-link" href="/tags/Java/">Java</a> <a class="tag-link" href="/tags/jls/">jls</a>    
        	
  </div>

</div>


<nav class="post-footer-nav">
  
    <div class="post-footer-link">
      <a href="/2018/10/12/数据库中-Blob-数据类型探究/" id="post-nav-newer" class="post-nav-link-wrap">
        <strong class="post-nav-caption">newer</strong>
           
          <a class="post-nav-title" href="/2018/10/12/数据库中-Blob-数据类型探究/">
          数据库中 Blob 数据类型探究</a>
      </a>
    </div>
  
  
    <div class="post-footer-link">
      <a href="/2018/09/26/Java-Interface一个知识点/" id="post-nav-older" class="post-nav-link-wrap">
        <strong class="post-nav-caption">older</strong>
        
          <a class="post-nav-title" href="/2018/09/26/Java-Interface一个知识点/">
          Java Interface一个知识点</a>
      </a>
    </div>
  
</nav>
 
	


    
    <div id="disqus_thread"></div>

    <script>
    (function() { 
    var d = document, s = d.createElement('script');
    s.src = 'https://'+'xiaohaoxing-github-io'+'.disqus.com/embed.js';
    s.setAttribute('data-timestamp', +new Date());    
    (d.head || d.body).appendChild(s);
    })();
    </script>

    <noscript>Please enable JavaScript to view the  <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a>
    </noscript>


	
</article>

          </section> 
      </div>            
    
    <a id="backTop">
      <span>
        <i class="iconfont icon-backtotop"></i>
      </span>
    </a> 

  
    
    <div class="search-container sildeUpMin">
        <div class="search-header">
            <input type="text" placeholder="输入你想搜索的" id="search-input" class="search-input">
            <span class="search-cancel">
                <i class="iconfont icon-cancel">
            </i></span>
        </div>
        <div id="search-result" class="search-result"></div>
    </div>
 
     <div class="mobile-menu">      

      
      <img class="mobile-menu-icon" src="/images/favicon.ico">   
      

         
            

            <a class="mobile-menu-link" href="/">首頁
            </a>
            
         
            

            <a class="mobile-menu-link" href="/archives">歸檔
            </a>
            
         
            

            <a class="mobile-menu-link" href="/tags">標籤
            </a>
            
         
            

            <a class="mobile-menu-link" href="/about">關於
            </a>
            
         
                          

            <a class="mobile-menu-link mobile-menu-search" href="#">搜索 </a>                 
            
         
      
</div>        
    



     
    




<footer id="footer">	    

		
		<div class="footer-copyright">
		&copy;
				
		2018-
		
		2019		
	
		XiaoHaoxing
		<br>

		Theme By
		<a href="https://github.com/Lemonreds/hexo-theme-Nayo" target="_blank">Nayo</a>	
		</div>			
		<script src="https://s19.cnzz.com/z_stat.php?id=1274862886&web_id=1274862886" language="JavaScript"></script>
</footer>   

  

    <script src="/nayo.bundle.js"></script>           
  </body>        
</html>